/**
 * File Name: ReciveEmailHelper.java
 * Description: 
 * Create Time: 2010-10-21
 * @Author: qiang.wu  ( qiang.wu@hisoft.com )
 */

package com.safx.mail;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.URLName;
import javax.mail.internet.MimeMessage;

import org.apache.log4j.Logger;

import com.safx.entity.env.MailEntity;

public class ReceiveEmailHelper {
	static Logger logger = Logger.getLogger(ReceiveEmailHelper.class);
	// private String sendServerAddrss = "smtp.sina.cn";
	private String reciveServerAddrss = "pop.sina.cn";
	private String protocal = "pop3";
	private int mailNum = 5;// this is you need number of e-mail
	private boolean readNewOnly = true;
	// private int port=110;
	private final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";

	public ReceiveEmailHelper() {

	}

	public ReceiveEmailHelper(boolean readNewOnly) {
		this.readNewOnly = readNewOnly;
	}

	public ReceiveEmailHelper(int mailNum) {
		this.mailNum = mailNum;
	}

	public ReceiveEmailHelper(int mailNum, boolean readNewOnly) {
		this.mailNum = mailNum;
		this.readNewOnly = readNewOnly;
	}

	public ReceiveEmailHelper(String reciveServerAddrss, String protocal, int mailNum, boolean readNewOnly) {
		this.reciveServerAddrss = reciveServerAddrss;
		this.protocal = protocal;
		this.mailNum = mailNum;
		this.readNewOnly = readNewOnly;
	}

	public String getReciveServerAddrss() {
		return reciveServerAddrss;
	}

	public void setReciveServerAddrss(String reciveServerAddrss) {
		this.reciveServerAddrss = reciveServerAddrss;
	}

	public String getProtocal() {
		return protocal;
	}

	public void setProtocal(String protocal) {
		this.protocal = protocal;
	}

	public int getMailNum() {
		return mailNum;
	}

	public void setMailNum(int mailNum) {
		this.mailNum = mailNum;
	}

	public boolean isReadNewOnly() {
		return readNewOnly;
	}

	public void setReadNewOnly(boolean readNewOnly) {
		this.readNewOnly = readNewOnly;
	}

	public static MailEntity getFirstMail(String email, String password, boolean readNewOnly, boolean needWait) throws NoSuchProviderException, MessagingException, Exception {
		// AccountEntity account=xmlHelper.ReadAccount("register");
		MailEntity mailEntity;
		ReceiveEmailHelper receiveEmailHelper = new ReceiveEmailHelper(readNewOnly);
		List<MailEntity> tempList = receiveEmailHelper.reciveMailWithCheck(email, password, needWait);
		mailEntity = (MailEntity) tempList.get(0);
		// firstLinksContent=mailEntity.getFirstLinksContent();

		return mailEntity;
	}

	public static MailEntity getFirstMailBySubject(String email, String password, boolean readNewOnly, String subject, boolean needWait) throws NoSuchProviderException, MessagingException {
		MailEntity mailEntity;
		ReceiveEmailHelper receiveEmailHelper = new ReceiveEmailHelper(readNewOnly);
		List<MailEntity> tempList = receiveEmailHelper.reciveMailWithCheck(email, password, needWait);
		for (int i = 0; i < tempList.size(); i++) {
			mailEntity = (MailEntity) tempList.get(i);
			// 根据邮件主题和收件人来收取第一封邮件
			if (mailEntity.getSubject().equals(subject) && mailEntity.getMailTo().contains(email)) {
				return mailEntity;
			}
		}
		return null;
	}

	/**
	 * 
	 * <b> </b>
	 * 
	 * @Author chenyue ( yue.chen2@hisoft.com ) Create on 2011-6-23
	 */
	public static MailEntity getFirstMailBySubjectAndmailTo(String email, String password, boolean readNewOnly, String subject, String mailTo, boolean needWait) throws NoSuchProviderException, MessagingException {
		MailEntity mailEntity;
		ReceiveEmailHelper receiveEmailHelper = new ReceiveEmailHelper(readNewOnly);
		List<MailEntity> tempList = receiveEmailHelper.reciveMailWithCheck(email, password, needWait);
		for (int i = 0; i < tempList.size(); i++) {
			mailEntity = (MailEntity) tempList.get(i);
			if (mailEntity.getSubject().equals(subject) && mailEntity.getMailTo().contains(email))
				return mailEntity;
		}
		return null;
	}

	@SuppressWarnings("deprecation")
	public static List<MailEntity> getTwoMailBySubject(String email, String password, boolean readNewOnly, String subject, boolean needWait) throws NoSuchProviderException, MessagingException, Exception {
		MailEntity mailEntity;
		ReceiveEmailHelper receiveEmailHelper = new ReceiveEmailHelper(readNewOnly);
		List<MailEntity> tempList = receiveEmailHelper.reciveMailWithCheck(email, password, needWait);
		// System.out.println("tempList size:"+tempList.size());
		List<MailEntity> mailEntityList = new ArrayList<MailEntity>();
		for (int i = 0; i < tempList.size() && i < 2; i++) {
			mailEntity = (MailEntity) tempList.get(i);
			if (mailEntity.getSubject().equals(subject)) {
				mailEntityList.add(mailEntity);
			}
		}
		if (new Date(mailEntityList.get(0).getSentDate()).compareTo(new Date(mailEntityList.get(1).getSentDate())) < 0) {
			mailEntityList.add(0, mailEntityList.remove(1));
		}
		return mailEntityList;
	}

	public List<MailEntity> reciveMailWithCheck(String email, String password, boolean needWait) throws NoSuchProviderException, MessagingException {
		boolean flag = true;
		int reConnectCount = 0;
		List<MailEntity> mailEntityList = null;
		try {
			logger.info("Waiting for email to arrive, please wait...");
			if (needWait) {
				Thread.sleep(60000);
			}
			logger.info("Receiving email, please wait...");
		} catch (InterruptedException e1) {
			logger.error(e1.getMessage());
		}
		while (flag) {
			try {
				mailEntityList = reciveMail(email, password);
				flag = false;
			} catch (MessagingException e) {
				flag = true;
				if (reConnectCount++ > 3) {
					flag = false;
					throw new MessagingException("Cannot connect email server,please check your email server");
				}
			} catch (Exception e) {
				logger.error(e.getMessage());
			}
		}
		if (mailEntityList == null || mailEntityList.isEmpty()) {
			logger.error("The mail is null.");
			throw new MessagingException("The mail is null.");
		}
		return mailEntityList;
	}

	public List<MailEntity> reciveMail(String email, String password) throws NoSuchProviderException, MessagingException, Exception {
		if (email.indexOf("+") != -1) {
			email = email.substring(0, email.indexOf("+")) + email.substring(email.indexOf("@"));
		}
		boolean reciveFlag = false;
		ReceiveEmail pmm = null;
		List<MailEntity> mailEntityList = new ArrayList<MailEntity>();
		MailEntity mailEntity;

		Store store = chooseMailServer(email, password);

		for (int times = 0; times < 3 && !reciveFlag; times++) {
			Folder folder = store.getFolder("INBOX");
			folder.open(Folder.READ_ONLY);
			Message message[] = folder.getMessages();
			if (message.length > 0) {
				// 获取第一封邮件
				for (int i = message.length - 1; i > message.length - mailNum - 1 && i >= 0; i--) {
					pmm = new ReceiveEmail((MimeMessage) message[i]);
					if (readNewOnly ? !pmm.isNew() : true) {
						mailEntity = new MailEntity();
						mailEntity.setSubject(pmm.getSubject());
						mailEntity.setSentDate(pmm.getSentDate());
						mailEntity.setHasRead(pmm.isNew());
						mailEntity.setFrom(pmm.getFrom());
						mailEntity.setFromPersonal(pmm.getFromPersonal());
						mailEntity.setFromAddress(pmm.getFromAddress());
						mailEntity.setMailTo(pmm.getMailAddress("to"));
						// 获得邮件内容===============
						pmm.getMailContent((Part) message[i]);
						mailEntity.setContentText(pmm.getBodyText().get(0));
						mailEntity.setContent(pmm.getBodyText().get(1));
						// 存储附件
						// pmm.setAttachPath("c:\\");
						// pmm.saveAttachMent((Part) message[i]);
						mailEntityList.add(mailEntity);
						// System.out.println("SUCCESS");
						reciveFlag = true;
						// pmm.isRead();
					} else {
						continue;
					}
				}

			} else {
				Thread.sleep(30000);
			}
			folder.close(false);
		}
		store.close();
		return mailEntityList;
	}

	public Store chooseMailServer(String email, String password) throws NoSuchProviderException, MessagingException, Exception {
		String temp = email.substring(email.indexOf("@") + 1, email.lastIndexOf("."));
		if (temp.equals("gmail")) {
			return setGmailFieldAndConnect(email, password);
		} else if (temp.equals("sina")) {
			return setFieldAndConnect(email, password);
		} else {
			logger.error("does support the email type, only support gmail and sina.");
			return null;
		}
	}

	private Store setGmailFieldAndConnect(String email, String password) throws NoSuchProviderException, MessagingException, Exception {
		String temp = email.substring(email.indexOf("@") + 1);
		Properties props = System.getProperties();
		props.setProperty("mail.pop3.socketFactory.class", SSL_FACTORY);
		props.setProperty("mail.pop3.socketFactory.fallback", "false");
		props.setProperty("mail.pop3.port", "995");
		props.setProperty("mail.pop3.socketFactory.port", "995");
		props.put("mail.smtp.host", "pop." + temp);
		props.put("mail.smtp.auth", "true");
		Session session = Session.getDefaultInstance(props, null);
		URLName urln = new URLName(protocal, "pop." + temp, 995, null, email.substring(0, email.indexOf("@")), password);
		Store store = session.getStore(urln.getProtocol());
		store.connect("pop." + temp, email.substring(0, email.indexOf("@")), password);
		return store;
	}

	private Store setFieldAndConnect(String email, String password) throws NoSuchProviderException, MessagingException, Exception {
		String temp = email.substring(email.indexOf("@") + 1);
		Properties props = System.getProperties();
		props.put("mail.smtp.host", "pop." + temp);
		props.put("mail.smtp.auth", "true");
		Session session = Session.getDefaultInstance(props, null);
		URLName urln = new URLName(protocal, "pop." + temp, 110, null, email.substring(0, email.indexOf("@")), password);
		Store store = session.getStore(urln.getProtocol());
		store.connect("pop." + temp, email.substring(0, email.indexOf("@")), password);
		return store;
	}

}
